package com.chenyun.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chenyun.common.utils.StringUtils;
import com.chenyun.system.mapper.SysRegionMapper;
import com.chenyun.system.model.SysRegion;
import com.chenyun.system.service.ISysRegionService;
import com.chenyun.system.vo.TreeSelect;
import com.chenyun.tenant.aop.TenantIgnore;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 省市区
 *
 * @author: Lonni
 * @date: 2022/11/7 0007 16:38
 */
@Service
public class SysRegionServiceImpl extends ServiceImpl<SysRegionMapper, SysRegion> implements ISysRegionService {


    /**
     * 获取所有省份
     *
     * @return
     */
    @Override
    @Cacheable(cacheNames = "sys", key = "'pro'")
    public List<SysRegion> getProvinces() {
        LambdaQueryWrapper<SysRegion> wrapper = Wrappers.<SysRegion>lambdaQuery()
                .eq(SysRegion::getPCode, "0")
                .eq(SysRegion::getLevel, "1");
        return this.list(wrapper);
    }

    /**
     * 根据省份id获取所有城市
     *
     * @param proCode
     * @return
     */
    @Override
    @Cacheable(cacheNames = "sys", key = "#proCode")
    public List<SysRegion> getCityByProId(String proCode) {
        LambdaQueryWrapper<SysRegion> wrapper = Wrappers.<SysRegion>lambdaQuery()
                .eq(SysRegion::getPCode, proCode)
                .eq(SysRegion::getLevel, "2");
        return this.list(wrapper);
    }

    /**
     * 根据城市id获取所有区
     *
     * @param cid
     * @return
     */
    @Override
    @Cacheable(cacheNames = "sys", key = "#cid")
    public List<SysRegion> getAreaByCityId(String cid) {
        LambdaQueryWrapper<SysRegion> wrapper = Wrappers.<SysRegion>lambdaQuery()
                .eq(SysRegion::getPCode, cid)
                .eq(SysRegion::getLevel, "3");
        return this.list(wrapper);
    }

    /**
     * 根据区域id获取街道
     *
     * @param aid@return
     */
    @Override
    @Cacheable(cacheNames = "sys", key = "#aid")
    public List<SysRegion> getStreetByAreaId(String aid) {
        LambdaQueryWrapper<SysRegion> wrapper = Wrappers.<SysRegion>lambdaQuery()
                .eq(SysRegion::getPCode, aid)
                .eq(SysRegion::getLevel, "4");
        return this.list(wrapper);
    }


    /**
     * 构建前端所需要树结构
     * 在这里最终生成树状结构
     *
     * @return 树结构列表
     */
    @Override
    @Cacheable(cacheNames = "sys", key = "'regionTree'+#level")
    @TenantIgnore
    public List<TreeSelect> builderTreeSelect(String level) {
        List<SysRegion> regions = new ArrayList<>();
        if (StringUtils.isNotBlank(level)) {
            regions = this.list(Wrappers.<SysRegion>lambdaQuery().eq(SysRegion::getLevel, level));
        } else {
            regions = this.list();
        }
        List<SysRegion> deptTrees = buildRegionTree(regions);
        return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }


    /**
     * 构建前端所需要树结构
     *
     * @param regions
     * @return 树结构列表
     */
    @Override
    public List<SysRegion> buildRegionTree(List<SysRegion> regions) {
        List<SysRegion> returnList = new ArrayList<SysRegion>();
        List<Long> tempList = new ArrayList<Long>();
        for (SysRegion dept : regions) {
            tempList.add(Long.valueOf(dept.getCode()));
        }
        for (Iterator<SysRegion> iterator = regions.iterator(); iterator.hasNext(); ) {
            SysRegion dept = (SysRegion) iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(Long.valueOf(dept.getPCode()))) {
                recursionFn(regions, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = regions;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysRegion> list, SysRegion t) {
        // 得到子节点列表
        List<SysRegion> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysRegion tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysRegion> getChildList(List<SysRegion> list, SysRegion t) {
        List<SysRegion> tlist = new ArrayList<SysRegion>();
        Iterator<SysRegion> it = list.iterator();
        while (it.hasNext()) {
            SysRegion n = (SysRegion) it.next();
            if (Objects.nonNull(n.getPCode()) && n.getPCode().equals(t.getCode())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysRegion> list, SysRegion t) {
        return getChildList(list, t).size() > 0;
    }

}



